package com.unitd.configclient.springboot;

import com.unitd.configclient.ConfigcenterContext;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.boot.env.PropertySourceLoader;
import org.springframework.core.PriorityOrdered;
import org.springframework.core.env.PropertiesPropertySource;
import org.springframework.core.env.PropertySource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PropertiesLoaderUtils;

import java.io.IOException;
import java.util.Properties;

/**
 * @desc 自定义PropertySourceLoader就需要实现接口类,并配置到spring.factories中
 * 通过自定义的PropertySourceLoader类来实现加载远程配置中心服务端的属性配置信息
 * @filename ConfigCenterPropertySourceLoader.java
 * @copyright www.pactera.com.cn
 * @author Hudan
 * @version 1.0
 * @date 2018/1/13
 */
public class ConfigCenterPropertySourceLoader implements PropertySourceLoader, PriorityOrdered, DisposableBean {

	/** 配置中心上下文对象信息 */
	private ConfigcenterContext ccContext = ConfigcenterContext.getInstance();

	/**
	 * @desc 获取属性文件的后缀名
	 * @return 属性文件的后缀名
	 */
	@Override
	public String[] getFileExtensions() {
		return new String[]{"properties"};
	}

	/**
	 * @desc 获取指定资源下的属性配置对象信息
	 * @param name 属性文件/对象名称
	 * @param resource 属性配置对象源
	 * @param profile 配置文件
	 * @return PropertySource
	 */
	@Override
	public PropertySource<?> load(String name, Resource resource, String profile) {
		if (profile == null) {
			Properties properties;
			try {
				properties = PropertiesLoaderUtils.loadProperties(resource);

				//  初始化方法, 获取当前配置中心客户端应用的属性配置信息
				ccContext.init(true);
				// 合并远程属性配置信息到本地
				ccContext.mergeRemoteProperties(properties);
				// 启动服务的时候, 从配置中心服务端获取初始配置信息
				ccContext.syncConfigToServer(properties, true);

				if (!properties.isEmpty()) {
					return new PropertiesPropertySource(name, properties);
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return null;
	}

	/**
	 * @desc 获取加载顺序
	 * @return int
	 */
	@Override
	public int getOrder() {
		return HIGHEST_PRECEDENCE;
	}

	/**
	 * @desc 继承Spring的DisposableBean类的destroy方法,每次调用完成后,都会去自动调用此方法,销毁当前应用上下文对象信息
	 */
	@Override
	public void destroy(){
		ccContext.close();
	}
}